package com.example.apidocserver.domain.document.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.example.apidocserver.domain.document.dao.DocMenuDao;
import com.example.apidocserver.domain.document.dto.MenuApiNodeDto;
import com.example.apidocserver.domain.document.dto.UploadMenuApiDto;
import com.example.apidocserver.domain.document.entity.DocMenu;
import com.example.apidocserver.domain.document.service.DocMenuService;
import com.example.apidocserver.infrastructure.constants.SystemConstants;
import com.example.apidocserver.infrastructure.util.result.ParamException;
import com.example.apidocserver.interfaces.vo.OrderChangeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 接口目录(DocMenu)表服务实现类
 *
 * @author makejava
 * @since 2023-02-22 22:17:47
 */
@Service("docMenuService")
@Slf4j
public class DocMenuServiceImpl implements DocMenuService {
    @Resource
    private DocMenuDao docMenuDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public DocMenu queryById(Integer id) {
        return this.docMenuDao.queryById(id);
    }

    /**
     * 查询所有对象
     *
     * @return 查询结果
     */
    @Override
    public List<DocMenu> queryAll() {
        return this.docMenuDao.queryAll();
    }

    /**
     * 根据对象查询
     *
     * @param docMenu 筛选条件
     * @return 查询结果
     */
    @Override
    public List<DocMenu> queryByEntity(DocMenu docMenu) {
        return this.docMenuDao.queryByEntity(docMenu);
    }

    /**
     * 新增数据
     *
     * @param docMenu 实例对象
     * @return 实例对象
     */
    @Override
    public DocMenu insert(DocMenu docMenu) {
        this.docMenuDao.insert(docMenu);
        return docMenu;
    }

    /**
     * 修改数据
     *
     * @param docMenu 实例对象
     * @return 实例对象
     */
    @Override
    public DocMenu update(DocMenu docMenu) {
        this.docMenuDao.update(docMenu);
        return this.queryById(docMenu.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.docMenuDao.deleteById(id) > 0;
    }

    @Override
    public List<DocMenu> find(Integer docId, boolean writeFlag) {
        return this.docMenuDao.queryByEntity(new DocMenu().setDocId(docId).setEnableFlag(writeFlag ? 0 : 1));
    }

    @Override
    public DocMenu upsertDocMenu(DocMenu docMenuIn) {
        // 1.查询通层排序最大值
        Integer maxOrder = this.docMenuDao.queryMaxOrder(docMenuIn.getDocId(), docMenuIn.getParentId());
        maxOrder = Objects.isNull(maxOrder) ? 1 : maxOrder + 1;
        docMenuIn.setUpdateTime(new Date());

        if (Objects.isNull(docMenuIn.getId())) {
            // 2.1.新增目录对象
            docMenuIn.setOrderNo(maxOrder).setCreateTime(docMenuIn.getUpdateTime());
            docMenuDao.insert(docMenuIn);
        } else {
            // 2.2.修改目录
            DocMenu docMenu = docMenuDao.queryById(docMenuIn.getId());
            if (Objects.isNull(docMenu)) {
                throw new ParamException("该目录已不存在。");
            }
            docMenuDao.update(docMenuIn);
        }
        return docMenuDao.queryById(docMenuIn.getId());
    }

    @Override
    public int orderChangeMenu(OrderChangeVo params) {
        DocMenu moveMenu = docMenuDao.queryById(params.getMoveId());
        DocMenu dropMenu = docMenuDao.queryById(params.getDropId());
        int oldOrder = moveMenu.getOrderNo();

        boolean afterFlag = moveMenu.getOrderNo() > dropMenu.getOrderNo();
        if (!Objects.equals(moveMenu.getParentId(), dropMenu.getParentId())) {
            moveMenu.setParentId(dropMenu.getParentId()).setIdPath(dropMenu.getIdPath());
            afterFlag = true;
            oldOrder = 9999999;
        }
        if (params.getType() == 0) {
            moveMenu.setOrderNo(dropMenu.getOrderNo());
        } else {
            moveMenu.setOrderNo(dropMenu.getOrderNo() + 1);
        }

        if (afterFlag) {
            docMenuDao.orderIncr(dropMenu.getParentId(), moveMenu.getOrderNo() - 1, oldOrder);
        } else {
            docMenuDao.orderDecr(dropMenu.getParentId(), moveMenu.getOrderNo() + 1, oldOrder);
        }
        docMenuDao.update(moveMenu);
        return 1;
    }

    @Override
    public int deleteMenu(Integer id) {
        return docMenuDao.deleteAndChildrenById(id);
    }

    @Override
    public void insertMenuTrees(UploadMenuApiDto menuApiDto) {
        List<DocMenu> menuInList = menuApiDto.getMenuList();
        if (CollectionUtils.isEmpty(menuInList)) {
            return;
        }
        Integer maxOrder = docMenuDao.queryMaxOrder(menuInList.get(1).getDocId(), SystemConstants.DATA_COMMON_ID);
        if (Objects.isNull(maxOrder)) {
            maxOrder = 1;
        }

        // 1.顶级目录重新排序、接口设置接口关联id
        List<MenuApiNodeDto> menuNodeList = menuApiDto.getMenuNodeList();
        menuNodeList.sort(Comparator.comparing(MenuApiNodeDto::getLvl));
        for (MenuApiNodeDto node : menuNodeList) {
            if (node.getLvl() == 1) {
                node.getNode().setOrderNo(node.getNode().getOrderNo() + maxOrder);
            } else if (node.getLvl() > 1) {
                break;
            }
        }

        // 2.插入文档对象
        this.docMenuDao.insertBatch(menuInList);

        // 3.修改目录
        for (MenuApiNodeDto node : menuNodeList) {
            String idPath = node.getParentNode().getIdPath();
            if (!StringUtils.isEmpty(idPath)) {
                idPath += ",";
            }
            idPath += node.getParentNode().getId();
            node.getNode().setParentId(node.getParentNode().getId()).setIdPath(idPath);
            if (Objects.nonNull(node.getApiInfo())) {
                node.getNode().setApiId(node.getApiInfo().getId());
            }
        }
        this.docMenuDao.insertOrUpdateBatch(menuInList);
    }
}
